package com.project.collectAPI.comm;


import com.aliyun.oss.*;
import com.aliyun.oss.model.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author sdx
 * @version 1.0
 * @date 2020/8/4 11:13
 */
@Service
@Slf4j
public class AliyunOssUtils {

    private static final String oss_accesskey_id = "LTAI5t94vCmLvDH1axkZ7rYG";
    private static final String oss_key_secret = "HkyO96bqBmeK97aRQtv3vOeVHbyKD9"; // OssSecret 在创建的时候只显示一次
    private static final String oss_domain = "https://aigxyy.oss-cn-shenzhen.aliyuncs.com";
    private static final String oss_bucket_name = "aigxyy";
    private static final String oss_endpoint = "https://oss-cn-shenzhen.aliyuncs.com";
    private static String dirname ="uploadimgs"; //网站资源图
    //private static final String dirusers ="users"; //用户病例png pdf jpg资源图
    //private static final String videodir ="videos";  //视频存放目录

    /**
     * 原文件名
     * @param multipartFile
     *  @param imagePathName bucket目录下的 images、users等目录
     * @return
     */
    public static String newUploadFile(MultipartFile multipartFile,String imagePathName){
        File file=transferToFile(multipartFile); //multipartFile 文件类型转换为 file类型
        log.info("=========>OSS文件上传开始："+file.getName());
        if(null == file){
            return null;
        }
        if(!StringUtils.isEmpty(imagePathName)){
            dirname=imagePathName; //接受上传的目录
        }
        OSS ossClient = new OSSClientBuilder().build(oss_endpoint, oss_accesskey_id, oss_key_secret);
        try {
            //容器不存在，就创建
            if(!ossClient.doesBucketExist(oss_bucket_name)){
                ossClient.createBucket(oss_bucket_name);
                CreateBucketRequest createBucketRequest = new CreateBucketRequest(oss_bucket_name);
                createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
                ossClient.createBucket(createBucketRequest);
            }
            //创建文件路径
            String fileUrl = (dirname + "/" +file.getName());
            //上传文件
            PutObjectResult result = ossClient.putObject(new PutObjectRequest(oss_bucket_name, fileUrl, file));
            //设置权限 这里是公开读
            ossClient.setBucketAcl(oss_bucket_name,CannedAccessControlList.PublicRead);
            if(null != result){
                //log.info("==========>OSS文件上传成功,OSS地址："+fileUrl);
                System.out.println("==========>OSS文件上传成功,OSS地址："+(oss_domain+"/"+fileUrl));
                return oss_domain+"/"+fileUrl;
            }
        }catch (OSSException oe){
            log.error(oe.getMessage());
        }catch (ClientException ce){
            log.error(ce.getMessage());
        }finally {
            //关闭
            ossClient.shutdown();
        }
        return null;
    }


    /**
     * bucket目录下的 images、users等目录
     * */
    public static String newUploadFile(File file,String imagePathName){
        log.info("=========>OSS文件上传开始："+file.getName());
        if(null == file){
            return null;
        }
        if(!StringUtils.isEmpty(imagePathName)){
            dirname=imagePathName;
        }
        OSS ossClient = new OSSClientBuilder().build(oss_endpoint, oss_accesskey_id, oss_key_secret);

        try {
            //容器不存在，就创建
            if(!ossClient.doesBucketExist(oss_bucket_name)){
                ossClient.createBucket(oss_bucket_name);
                CreateBucketRequest createBucketRequest = new CreateBucketRequest(oss_bucket_name);
                createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
                ossClient.createBucket(createBucketRequest);
            }
            //创建文件路径
            String fileUrl = (dirname + "/" +file.getName());
            //上传文件
            PutObjectResult result = ossClient.putObject(new PutObjectRequest(oss_bucket_name, fileUrl, file));
            //设置权限 这里是公开读
            ossClient.setBucketAcl(oss_bucket_name,CannedAccessControlList.PublicRead);
            if(null != result){
                //log.info("==========>OSS文件上传成功,OSS地址："+fileUrl);
                System.out.println("==========>OSS文件上传成功,OSS地址："+(oss_domain+"/"+fileUrl));
                return oss_domain+"/"+fileUrl;
            }
        }catch (OSSException oe){
            log.error(oe.getMessage());
        }catch (ClientException ce){
            log.error(ce.getMessage());
        }finally {
            //关闭
            ossClient.shutdown();
        }
        return null;
    }

    /**
     * MultipartFile类型 转 File类型
     * @param multipartFile
     * @return
     */
    private static File transferToFile(MultipartFile multipartFile) {
        //选择用缓冲区来实现这个转换即使用java 创建的临时文件 使用 MultipartFile.transferto()方法 。
        File file = null;
        try {
            String originalFilename = multipartFile.getOriginalFilename();
            String[] filename = originalFilename.split("\\.");
            file=File.createTempFile(filename[0],"."+filename[1]);
            multipartFile.transferTo(file);
            file.deleteOnExit();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return file;
    }

    /**
     * 上传
     * @param file
     * @return
     */
    public static String upload(File file,String endpoint,String accessKeyId,String accessKeySecret,String bucketName,String fileHost,String dateStr){
        log.info("=========>OSS文件上传开始："+file.getName());

        if(null == file){
            return null;
        }

        OSSClient ossClient = new OSSClient(endpoint,accessKeyId,accessKeySecret);
        try {
            //容器不存在，就创建
            if(! ossClient.doesBucketExist(bucketName)){
                ossClient.createBucket(bucketName);
                CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
                createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
                ossClient.createBucket(createBucketRequest);
            }
            //创建文件路径
            String fileUrl = (dateStr + "/" + UUID.randomUUID().toString().replace("-","")+"-"+file.getName());
            //上传文件
            PutObjectResult result = ossClient.putObject(new PutObjectRequest(bucketName, fileUrl, file));
            //设置权限 这里是公开读
            ossClient.setBucketAcl(bucketName,CannedAccessControlList.PublicRead);
            if(null != result){
                log.info("==========>OSS文件上传成功,OSS地址："+fileUrl);
                return fileHost+"/"+fileUrl;
            }
        }catch (OSSException oe){
            log.error(oe.getMessage());
        }catch (ClientException ce){
            log.error(ce.getMessage());
        }finally {
            //关闭
            ossClient.shutdown();
        }
        return null;
    }

    /**
     * 原文件名
     * @param file
     * @param endpoint
     * @param accessKeyId
     * @param accessKeySecret
     * @param bucketName
     * @param fileHost
     * @param dateStr
     * @return
     */
    public static String uploadFile(File file,String endpoint,String accessKeyId,String accessKeySecret,String bucketName,String fileHost,String dateStr){
        log.info("=========>OSS文件上传开始："+file.getName());

        if(null == file){
            return null;
        }

        OSSClient ossClient = new OSSClient(endpoint,accessKeyId,accessKeySecret);
        try {
            //容器不存在，就创建
            if(! ossClient.doesBucketExist(bucketName)){
                ossClient.createBucket(bucketName);
                CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
                createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
                ossClient.createBucket(createBucketRequest);
            }
            //创建文件路径
            String fileUrl = (dateStr + "/" +file.getName());
            //上传文件
            PutObjectResult result = ossClient.putObject(new PutObjectRequest(bucketName, fileUrl, file));
            //设置权限 这里是公开读
            ossClient.setBucketAcl(bucketName,CannedAccessControlList.PublicRead);
            if(null != result){
                log.info("==========>OSS文件上传成功,OSS地址："+fileUrl);
                return fileHost+"/"+fileUrl;
            }
        }catch (OSSException oe){
            log.error(oe.getMessage());
        }catch (ClientException ce){
            log.error(ce.getMessage());
        }finally {
            //关闭
            ossClient.shutdown();
        }
        return null;
    }

    /**
     * 批量下载oss 文件 并打成zip 包 返回到response中
     *
     * @param fileNames oss上的文件名集合 如：product/image/3448275920.png
     * @param zipFileName 压缩包文件名
     * @param response  HttpServletResponse
     */
    public static void batchDownLoadOssFile(List<String> fileNames, String zipFileName, HttpServletResponse response
    ,String endpoint,String accessKeyId,String accessKeySecret,String bucketName) {
        response.setCharacterEncoding("utf-8");
        response.setContentType("multipart/form-data");
        response.setHeader("Content-Disposition", "attachment;fileName=" + zipFileName + ".zip");
        BufferedInputStream bis = null;
        try {
            ZipOutputStream zos = new ZipOutputStream(response.getOutputStream());
            OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
            int sortNum = 0;
            for (String fileName : fileNames) {
                Date expiration = new Date(System.currentTimeMillis() + 3600 * 1000);
                GeneratePresignedUrlRequest request = new GeneratePresignedUrlRequest(bucketName, fileName, HttpMethod.GET);
                // 设置过期时间。
                request.setExpiration(expiration);
                // 生成签名URL（HTTP GET请求）。
                URL signedUrl = ossClient.generatePresignedUrl(request);
                // 使用签名URL发送请求。
                OSSObject ossObject = ossClient.getObject(signedUrl, new HashMap<>());

                if (ossObject != null) {
                    InputStream inputStream = ossObject.getObjectContent();
                    byte[] buffs = new byte[1024 * 10];

                    String zipFile = sortNum + "_" + fileName.substring(fileName.lastIndexOf("/") + 1);
                    ZipEntry zipEntry = new ZipEntry(zipFile);
                    zos.putNextEntry(zipEntry);
                    bis = new BufferedInputStream(inputStream, 1024 * 10);

                    int read;
                    while ((read = bis.read(buffs, 0, 1024 * 10)) != -1) {
                        zos.write(buffs, 0, read);
                    }
                    ossObject.close();
                }
                sortNum++;
            }
            zos.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            //关闭流
            try {
                if (null != bis) {
                    bis.close();
                }
                response.getOutputStream().flush();
                response.getOutputStream().close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public static void deleteFile(String folder, String fileName,String endpoint,String accessKeyId,String accessKeySecret,String bucketName){
        OSS client=new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        String key;
        if(StringUtils.isEmpty(folder)){
            key = fileName;
        }else{
            key = folder +"/"+ fileName;
        }
        client.deleteObject(bucketName,key);
        client.shutdown();
    }
}
